package com.agileai.bpm.service.running;

import java.util.HashMap;
import java.util.List;

import org.apache.log4j.Logger;

import com.agileai.bpm.common.BPMConstants;
import com.agileai.bpm.domain.define.Process;
import com.agileai.bpm.domain.running.ActivityInstance;
import com.agileai.bpm.domain.running.DelegateItem;
import com.agileai.bpm.domain.running.HandleItem;
import com.agileai.bpm.domain.running.InvokeItem;
import com.agileai.bpm.domain.running.LaunchItem;
import com.agileai.bpm.domain.running.ProcessInstance;
import com.agileai.bpm.domain.running.SubmitItem;
import com.agileai.bpm.domain.running.WorkItem;
import com.agileai.domain.DataRow;
import com.agileai.util.DateUtil;

public class ProcessHandleImpl implements ProcessHandle{
	private static final Logger loger = Logger.getLogger(ProcessHandleImpl.class);
	private ProcessEngine engine = null;
	
	public ProcessHandleImpl(){
		
	}
	
	public String[] getProcessId8InstId(String processCode,String bizRecordId){
		String[] result = new String[2];
		DataRow row = this.engine.getProcessId8InstIdRow(processCode, bizRecordId);
		if (row != null && !row.isEmpty()){
			result[0] = row.getString("WFP_ID");
			result[1] = row.getString("WFIP_ID");
		}
		return result;
	}
	
	public String launchProcess(LaunchItem launchWorkItem,boolean skipFirstNode) throws RunningException {
		String msgPrefix = "launchProcess() - ";
		loger.debug(msgPrefix + "-----START");

		String userId = launchWorkItem.getUserId();
		DataRow userRow = engine.findUserRow(userId,UserSeqType.USER_ID); 
		if (userRow == null || userRow.isEmpty()){
			throw new RunningException(userId +" not exisit !");
		}
		
		ProcessInstance processInstance = new ProcessInstance();
		Process process = engine.retrieveProcess(launchWorkItem.getProcessId());
		processInstance.setProcess(process);
		processInstance.setLaucherId(userId);		
		String userName = userRow.getString("USER_NAME");
		processInstance.setLaucherName(userName);
		processInstance.setTitle(launchWorkItem.getTitle());
		processInstance.setLaucheTime(DateUtil.getDateByType(DateUtil.YYMMDDHHMISS_HORIZONTAL));
		processInstance.setProcessId(launchWorkItem.getProcessId());
		
		processInstance.setOperaterId(userId);
		processInstance.setOperaterName(userName);
		processInstance.setOperateTime(DateUtil.getDateByType(DateUtil.YYMMDDHHMISS_HORIZONTAL));
		
		processInstance.setBizRecordId(launchWorkItem.getBizRecordId());
		processInstance.setBizRecordCode(launchWorkItem.getBizRecordCode());
		engine.createInstance(processInstance,launchWorkItem.getWorkAttributes(),skipFirstNode);
		
		loger.debug(msgPrefix + "-----END");
	
		return processInstance.getId();
	}
	public void submitProcess(SubmitItem submitItem,ProcessInstance processInstance) throws RunningException {
		String msgPrefix = "submitProcess() - ";
		loger.debug(msgPrefix + "-----START");
		String userId = submitItem.getUserId();
		DataRow userRow = engine.findUserRow(userId,UserSeqType.USER_ID); 
		if (userRow == null || userRow.isEmpty()){
			throw new RunningException(userId +" not exisit !");
		}
		
		processInstance.setOperaterId(userId);
		String userName = userRow.getString("USER_NAME");
		processInstance.setOperaterName(userName);
		processInstance.setOperateTime(DateUtil.getDateByType(DateUtil.YYMMDDHHMISS_HORIZONTAL));
		HashMap<String,ActivityInstance> activityInstances =  processInstance.getActivityInstances();
		String activityCode = submitItem.getActivityCode();
		ActivityInstance activityInstance = activityInstances.get(activityCode);
		engine.transitInstance(activityInstance,submitItem.getWorkAttributes());
		
		loger.debug(msgPrefix + "-----END");
	}
	
	public void invokeProcess(InvokeItem invokeItem,ProcessInstance processInstance) throws RunningException {
		String msgPrefix = "invokeProcess() - ";
		loger.debug(msgPrefix + "-----START");
		
		String userCode = BPMConstants.SERVICE_USER_ID;
		DataRow userRow = engine.findUserRow(userCode,UserSeqType.USER_CODE); 
		if (userRow == null || userRow.isEmpty()){
			throw new RunningException(userCode +" not exisit !");
		}
		
		String userId = userRow.getString("USER_ID");
		String userName = userRow.getString("USER_NAME");
		processInstance.setOperaterId(userId);
		processInstance.setOperaterName(userName);
		processInstance.setOperateTime(DateUtil.getDateByType(DateUtil.YYMMDDHHMISS_HORIZONTAL));
		HashMap<String,ActivityInstance> activityInstances =  processInstance.getActivityInstances();
		String activityCode = invokeItem.getActivityCode();
		ActivityInstance activityInstance = activityInstances.get(activityCode);
		engine.transitInstance(activityInstance,invokeItem.getWorkAttributes());
		
		loger.debug(msgPrefix + "-----END");
	}	
	
	public List<WorkItem> findWorkItemList(String seq,String type) {
		String msgPrefix = "findTaskItemList() - ";
		loger.debug(msgPrefix + "-----START");
		
		List<WorkItem> result = engine.findWorkItemList(seq,type);
		
		loger.debug(msgPrefix + "-----END");
		return result;
	}	
	
	public boolean isOwnTask(String userId, String processInstanceId, String activityCode) throws RunningException {
		String msgPrefix = "isOwnTask() - ";
		loger.debug(msgPrefix + "-----START");
		
		boolean result = false;
		result = engine.isOwnTaskItem(userId, processInstanceId, activityCode);
		
		loger.debug(msgPrefix + "-----END");
		return result;
	}
	
	public void resumeProcess(HandleItem processWorkItem) throws RunningException{
		String msgPrefix = "resumeProcess() - ";
		loger.debug(msgPrefix + "-----START");
		
		String processInstanceId = processWorkItem.getProcessInstId();
		ProcessInstance processInstance = engine.retrieveProcessInstance(processInstanceId);
		processInstance.setStatus(ProcessInstance.Status.running);
		engine.updateInstance(processInstance);
		engine.insertProcessLog(processInstance, HandleItem.Types.ResumeProcess, processWorkItem.getUserId(), null, null);
		
		loger.debug(msgPrefix + "-----END");
	}
	
	public void suspendProcess(HandleItem processWorkItem) throws RunningException {
		String msgPrefix = "suspendProcess() - ";
		loger.debug(msgPrefix + "-----START");
		
		String processInstanceId = processWorkItem.getProcessInstId();
		ProcessInstance processInstance = engine.retrieveProcessInstance(processInstanceId);
		processInstance.setStatus(ProcessInstance.Status.suspend);
		engine.updateInstance(processInstance);
		
		engine.insertProcessLog(processInstance, HandleItem.Types.SuspendProcess, processWorkItem.getUserId(), null, null);
		
		loger.debug(msgPrefix + "-----END");
	}
	
	public void terminateProcess(HandleItem processWorkItem) throws RunningException {
		String msgPrefix = "terminateProcess() - ";
		loger.debug(msgPrefix + "-----START");
		
		String processInstanceId = processWorkItem.getProcessInstId();
		ProcessInstance processInstance = engine.retrieveProcessInstance(processInstanceId);
		
		engine.terminateInstance(processInstanceId);
		engine.insertProcessLog(processInstance, HandleItem.Types.TerminateProcess, processWorkItem.getUserId(), null, null);
		
		loger.debug(msgPrefix + "-----END");
	}
	
	public ProcessEngine getEngine() {
		return engine;
	}
	
	public void setEngine(ProcessEngine engine) {
		this.engine = engine;
	}
	
	public Process retrieveProcess(String processId) throws RunningException {
		String msgPrefix = "retrieveProcess() - ";
		loger.debug(msgPrefix + "-----START");
		
		Process result = null;
		result = engine.retrieveProcess(processId);
		
		loger.debug(msgPrefix + "-----END");
		return result;
	}
	
	public String findUserId(String userCode) throws RunningException {
		String msgPrefix = "findUserId() - ";
		loger.debug(msgPrefix + "-----START");
		
		String result = null;
		DataRow row = engine.findUserRow(userCode, UserSeqType.USER_CODE); 
		result = row.getString("USER_ID");
		
		loger.debug(msgPrefix + "-----END");
		return result;
	}
	
	public String findUserCode(String userId) throws RunningException{
		String msgPrefix = "findUserCode() - ";
		loger.debug(msgPrefix + "-----START");
		
		String result = null;
		DataRow row = engine.findUserRow(userId, UserSeqType.USER_ID); 
		result = row.getString("USER_CODE");
		
		loger.debug(msgPrefix + "-----END");
		return result;
	}

	@Override
	public String findCurrentProcessId(String processCode) throws RunningException{
		String msgPrefix = "findCurrentProcessId() - ";
		loger.debug(msgPrefix + "-----START");
		
		String result = engine.findCurrentProcessId(processCode);
		
		loger.debug(msgPrefix + "-----END");
		return result;
	}

	@Override
	public ProcessInstance retrieveProcessInstance(String processInstId) throws RunningException {
		ProcessInstance result = null;
		String msgPrefix = "retrieveProcessInstance() - ";
		loger.debug(msgPrefix + "-----START");
		
		result = engine.retrieveProcessInstance(processInstId);
		
		loger.debug(msgPrefix + "-----END");
		return result;
	}

	@Override
	public void saveDraft(String processId, String userId, String bizRecordId,String bizTitle,String bizCode)
			throws RunningException {
		String msgPrefix = "saveDraft() - ";
		loger.debug(msgPrefix + "-----START");
		
		engine.saveDraft(processId, userId, bizRecordId,bizTitle,bizCode);
		
		loger.debug(msgPrefix + "-----END");
	}

	@Override
	public void delegateProcess(DelegateItem delegateItem)
			throws RunningException {
		String msgPrefix = "delegateProcess() - ";
		loger.debug(msgPrefix + "-----START");
		
		String processInstId = delegateItem.getProcessInstId();
		String activityInstId = delegateItem.getActivityInstId();
		String userId = delegateItem.getUserId();
		String delegateeId = delegateItem.getDelegateeId();
		engine.updateWorkItem(processInstId, activityInstId, userId, delegateeId);
		
		loger.debug(msgPrefix + "-----END");
	}

	@Override
	public String findActivityInstId(String processInstId, String userCode,
			String activityCode) throws RunningException {
		String msgPrefix = "findActivityInstId() - ";
		loger.debug(msgPrefix + "-----START");
		
		String result = null;
		DataRow row = this.engine.findWorkItemRow(processInstId, userCode, activityCode);
		if (row != null){
			result = row.getString("WFIA_ID");
		}
		
		loger.debug(msgPrefix + "-----END");
		return result;
	}
}
